package ray_tracer;

import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;

import javax.swing.JFrame;
import javax.vecmath.Color3f;

import light.AmbientLight;
import light.PointLight;

import object.HorizontalQuad;
import object.Sphere;
import object.Triangle;

import ray.CameraRay;
import scene.Scene;
import screen.ScreenBuffer;
import util.Point3D;

public class RayTracer {

	private ScreenBuffer buffer;
	private JFrame frame;

	public RayTracer() {
		this.buffer = new ScreenBuffer();
		this.frame = new JFrame("Ray Tracer - Assignment 7");

		this.frame.setSize((int) ScreenBuffer.SCREEN.getWidth() + 10,
				(int) ScreenBuffer.SCREEN.getHeight() + 10);
		this.frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
	}

	public void buildScene() {
		// Create spheres
		Sphere largeSphere = new Sphere("Large Sphere", new Point3D(0.05f,
				0.0f, 0.0f), 0.33f, new Color3f(0.5f, 0.0f, 0.0f), false, true);
		Sphere smallSphere = new Sphere("Small Sphere", new Point3D(-0.4f,
				-0.15f, -0.5f), 0.3f, new Color3f(0.0f, 0.5f, 0.0f), true, false);
		// Create Triangles for floor
		Triangle tLeft = new Triangle("Left Floor", new Point3D(-3.0f, -0.7f,
				1.0f), new Point3D(1.0f, -0.7f, 1.0f), new Point3D(-3.0f,
				-0.7f, -10.0f), new Color3f(0.0f, 0.0f, 1.0f));
		Triangle tRight = new Triangle("Right Floor", new Point3D(1.0f, -0.7f,
				1.0f), new Point3D(1.0f, -0.7f, -10.0f), new Point3D(-3.0f,
				-0.7f, -10.0f), new Color3f(0.0f, 0.0f, 1.0f));
		// Create floor quad
		HorizontalQuad floor = new HorizontalQuad("Floor", new Color3f(0.0f,
				0.0f, 0.5f), new Point3D(-3.0f, -0.7f, 1.0f), 4.0f, 11.0f);
		// Add objects to scene
		// Scene.getInstance().addSceneObject(tLeft);
		// Scene.getInstance().addSceneObject(tRight);
		Scene.getInstance().addSceneObject(floor);
		Scene.getInstance().addSceneObject(largeSphere);
		Scene.getInstance().addSceneObject(smallSphere);
		// Setup scene
		Scene.getInstance().setAmbientLight(
				new AmbientLight(new Color3f(0.1f, 0.1f, 0.1f)));
		Scene.getInstance().addPointLight(
				new PointLight(new Point3D(1.0f, 2.0f, 4.0f), new Color3f(1.0f,
						1.0f, 1.0f)));
//		Scene.getInstance().addPointLight(
//				new PointLight(new Point3D(-0.5f, 1.0f, 2.0f), new Color3f(
//						1.0f, 1.0f, 1.0f)));
	}

	public void renderScene(boolean useSuperSampling) {
		this.sample(Camera.NO_SHIFT);
		if (useSuperSampling) {
			this.sample(Camera.SHIFT_LEFT);
			this.sample(Camera.SHIFT_DOWN);
			this.sample(Camera.SHIFT_RIGHT);
			this.sample(Camera.SHIFT_UP);
		}
		frame.setVisible(true);
		buffer.draw((Graphics2D) frame.getGraphics());
	}

	private void sample(Rectangle2D shift) {
		CameraRay r;
		Scene.getInstance().getCamera().reset();
		Scene.getInstance().getCamera().setShift(shift);
		while (Scene.getInstance().getCamera().hasNextCameraRay()) {
			r = Scene.getInstance().getCamera().getNextCameraRay();
			buffer.addColorToPixel(r.getCorrespondingPixel(), r.getColor(1));
		}
	}

	public static void main(String[] args) {
		RayTracer tracer = new RayTracer();
		tracer.buildScene();
		tracer.renderScene(false);
	}

}
